/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package org.rcs.servlets.utils;

import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.annotations.XStreamOmitField;
import java.io.File;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 *
 * @author pablo
 */
public class XMLConfig {

  @XStreamOmitField
  private String fileName;
  @XStreamOmitField
  private long lastModified;

  private static <T extends XMLConfig> String getFileName(Class<? extends XMLConfig> clazz) {
    XMLFileName fileNameAnnotation = clazz.getAnnotation(XMLFileName.class);

    if (null == fileNameAnnotation)
      throw new InstantiationError(String.format("Class %s must have annotation XMLFileName", clazz.getName()));

    return fileNameAnnotation.value();
  }

  protected XMLConfig(Class clazz) {
    this.fileName = getFileName(clazz);
  }

  public String getFileName() {
    return this.fileName;
  }

  public boolean existsFile() {
    File file = FileUtils.getConfigFile(getFileName());

    return file.exists() ;
  }

  public boolean needUpdate() {
    File file = FileUtils.getConfigFile(getFileName());

    return lastModified != file.lastModified();
  }

  public static <T extends XMLConfig> T read(Class<? extends XMLConfig> clazz) {
    XStream stream = FileUtils.getXStream(clazz);
    File file = FileUtils.getConfigFile(getFileName(clazz));
    XMLConfig result = (XMLConfig) stream.fromXML(file);

    result.lastModified = file.lastModified();
    result.fileName = getFileName(clazz);

    return (T) result;
  }

  public void write() throws IOException {
    XStream stream = FileUtils.getXStream(getClass());
    FileUtils.getConfigDir().mkdirs();
    File outFile = FileUtils.getConfigFile(getFileName());
    OutputStreamWriter out = FileUtils.getConfigWriter(getFileName());

    stream.toXML(this, out);
    FileUtils.close(out);
    lastModified = outFile.lastModified();
  }

  public static <T extends XMLConfig> T get(T configObj, Class<T> clazz) {
    try {
      if (null == configObj) {
        configObj = clazz.newInstance();

        if (!configObj.existsFile()) {
          try {
            configObj.write();
          } catch (IOException ex) {
            // No se pudo guardar la configuración actual
            Logger.getLogger(XMLConfig.class.getName()).log(Level.SEVERE, null, ex);
          }
        }
      }

      if (configObj.needUpdate())
        configObj = XMLConfig.read(clazz);

      return configObj;
    } catch (InstantiationException ex) {
      Logger.getLogger(XMLConfig.class.getName()).log(Level.SEVERE, null, ex);
    } catch (IllegalAccessException ex) {
      Logger.getLogger(XMLConfig.class.getName()).log(Level.SEVERE, null, ex);
    }

    throw new IllegalStateException(String.format("Can't instanciate %s", clazz.getCanonicalName()));
  }
}
